// 版权所有2009年围棋作者。版权所有。
// 此源代码的使用受BSD样式的约束
// 可以在许可证文件中找到的许可证。

package bytes

// 用于封送数据的简单字节缓冲区。

import (
	"errors"
	"io"
	"unicode/utf8"
)

// smallBufferSize是初始分配的最小容量。
const smallBufferSize = 64

// 缓冲区是具有读写方法的字节大小可变的缓冲区。
// 缓冲区的零值是准备使用的空缓冲区。
type Buffer struct {
	buf      []byte // 内容是字节buf[off:len（buf）]
	off      int    // 读取at&buf[off]，写入at&buf[len（buf）]
	lastRead readOp // 上次读取操作，以便未读*可以正常工作。
}

// readOp常量描述在上执行的最后一个操作
// 缓冲区，以便UnreadRune和UnreadByte可以检查
// 无效用法。opReadRuneX常量的选择应确保
// 转换为int，它们对应于读取的符文大小。
type readOp int8

// 不要使用物联网，因为这些值需要与
// 名称和注释，显式时更容易看到。
const (
	opRead      readOp = -1 // 任何其他读取操作。
	opInvalid   readOp = 0  // 非读取操作。
	opReadRune1 readOp = 1  // 阅读1号符文。
	opReadRune2 readOp = 2  // 阅读2号符文。
	opReadRune3 readOp = 3  // 阅读3号符文。
	opReadRune4 readOp = 4  // 阅读4号符文。
)

// 如果无法分配内存将数据存储在缓冲区中，则会将ErrTooLarge传递给panic。
var ErrTooLarge = errors.New("bytes.Buffer: too large")
var errNegativeRead = errors.New("bytes.Buffer: reader returned negative count from Read")

const maxInt = int(^uint(0) >> 1)

// Bytes返回一个长度为b.Len（）的片段，该片段包含缓冲区的未读部分。
// 只有在下一次缓冲区修改（即，
// 直到下一次调用方法（如读、写、重置或截断）为止。
// 至少在下一次缓冲区修改之前，切片会为缓冲区内容添加别名，
// 因此，立即更改切片将影响将来读取的结果。
func (b *Buffer) Bytes() []byte { return b.buf[b.off:] }

// 字符串返回缓冲区未读部分的内容
// 一串。如果缓冲区是nil指针，则返回“<nil>”。
// None
// 要更有效地构建字符串，请参阅strings.Builder类型。
func (b *Buffer) String() string {
	if b == nil {
		// 特殊情况，在调试中很有用。
		return "<nil>"
	}
	return string(b.buf[b.off:])
}

// empty报告缓冲区的未读部分是否为空。
func (b *Buffer) empty() bool { return len(b.buf) <= b.off }

// Len返回缓冲区未读部分的字节数；
// b、 Len（）==Len（b.字节（）。
func (b *Buffer) Len() int { return len(b.buf) - b.off }

// Cap返回缓冲区底层字节片的容量，即
// 为缓冲区数据分配的总空间。
func (b *Buffer) Cap() int { return cap(b.buf) }

// Truncate丢弃缓冲区中除前n个未读字节以外的所有字节
// 但继续使用相同的已分配存储。
// 如果n为负数或大于缓冲区的长度，它将崩溃。
func (b *Buffer) Truncate(n int) {
	if n == 0 {
		b.Reset()
		return
	}
	b.lastRead = opInvalid
	if n < 0 || n > b.Len() {
		panic("bytes.Buffer: truncation out of range")
	}
	b.buf = b.buf[:b.off+n]
}

// 重置将缓冲区重置为空，
// 但它保留了底层存储以供将来写入使用。
// 重置与截断（0）相同。
func (b *Buffer) Reset() {
	b.buf = b.buf[:0]
	b.off = 0
	b.lastRead = opInvalid
}

// tryGrowByReslice是一个可内联版本的grow for fast案例，其中
// 内部缓冲区只需要重新许可。
// 它返回应该写入字节的索引以及是否成功。
func (b *Buffer) tryGrowByReslice(n int) (int, bool) {
	if l := len(b.buf); n <= cap(b.buf)-l {
		b.buf = b.buf[:l+n]
		return l, true
	}
	return 0, false
}

// grow增加缓冲区，以保证多容纳n个字节的空间。
// 它返回应该写入字节的索引。
// 如果缓冲区无法增长，它将因ErrTooLarge而死机。
func (b *Buffer) grow(n int) int {
	m := b.Len()
	// 如果缓冲区为空，请重置以恢复空间。
	if m == 0 && b.off != 0 {
		b.Reset()
	}
	// 试着用一根树枝来生长。
	if i, ok := b.tryGrowByReslice(n); ok {
		return i
	}
	if b.buf == nil && n <= smallBufferSize {
		b.buf = make([]byte, n, smallBufferSize)
		return 0
	}
	c := cap(b.buf)
	if n <= c/2-m {
		// 我们可以降低成本，而不是分配新的
		// 片我们只需要m+n<=c来滑动，但是
		// 相反，我们让容量增加两倍，因此
		// 不要把我们所有的时间都花在抄写上。
		copy(b.buf, b.buf[b.off:])
	} else if c > maxInt-c-n {
		panic(ErrTooLarge)
	} else {
		// 任何地方都没有足够的空间，我们需要分配。
		buf := makeSlice(2*c + n)
		copy(buf, b.buf[b.off:])
		b.buf = buf
	}
	// 恢复b.off和len（b.buf）。
	b.off = 0
	b.buf = b.buf[:m+n]
	return m
}

// 如有必要，增加缓冲区的容量，以保证
// 另外n个字节。在Grow（n）之后，至少可以将n个字节写入
// 没有另一个分配的缓冲区。
// 如果n为负，Grow将恐慌。
// 如果缓冲区无法增长，它将因ErrTooLarge而死机。
func (b *Buffer) Grow(n int) {
	if n < 0 {
		panic("bytes.Buffer.Grow: negative count")
	}
	m := b.grow(n)
	b.buf = b.buf[:m]
}

// Write将p的内容追加到缓冲区中，使缓冲区按
// 需要。返回值n是p的长度；错误总是零。如果
// 缓冲区太大，写入将因ErrTooLarge而死机。
func (b *Buffer) Write(p []byte) (n int, err error) {
	b.lastRead = opInvalid
	m, ok := b.tryGrowByReslice(len(p))
	if !ok {
		m = b.grow(len(p))
	}
	return copy(b.buf[m:], p), nil
}

// WriteString将s的内容追加到缓冲区，使缓冲区按
// 需要。返回值n是s的长度；错误总是零。如果
// 缓冲区太大，WriteString将因ErrTooLarge而死机。
func (b *Buffer) WriteString(s string) (n int, err error) {
	b.lastRead = opInvalid
	m, ok := b.tryGrowByReslice(len(s))
	if !ok {
		m = b.grow(len(s))
	}
	return copy(b.buf[m:], s), nil
}

// MinRead是传递给读取调用的最小片大小
// Buffer.ReadFrom。只要缓冲区的最小读取字节数超过
// 保存r，ReadFrom的内容所需的内容不会增长
// 底层缓冲区。
const MinRead = 512

// ReadFrom从r读取数据，直到EOF，并将其附加到缓冲区，不断增长
// 根据需要设置缓冲区。返回值n是读取的字节数。任何
// 读取过程中遇到的io.EOF之外的错误也会返回。如果
// 缓冲区太大，ReadFrom将因ErrTooLarge而死机。
func (b *Buffer) ReadFrom(r io.Reader) (n int64, err error) {
	b.lastRead = opInvalid
	for {
		i := b.grow(MinRead)
		b.buf = b.buf[:i]
		m, e := r.Read(b.buf[i:cap(b.buf)])
		if m < 0 {
			panic(errNegativeRead)
		}

		b.buf = b.buf[:i+m]
		n += int64(m)
		if e == io.EOF {
			return n, nil // e是EOF，所以显式返回nil
		}
		if e != nil {
			return n, e
		}
	}
}

// makeSlice分配大小为n的片。如果分配失败，它就会恐慌
// 用ErrTooLarge。
func makeSlice(n int) []byte {
	// 如果make失败，请给出一个已知错误。
	defer func() {
		if recover() != nil {
			panic(ErrTooLarge)
		}
	}()
	return make([]byte, n)
}

// WriteTo将数据写入w，直到缓冲区耗尽或发生错误。
// 返回值n是写入的字节数；它总是适合你的生活
// int，但与io.WriterTo接口匹配的是int64。任何错误
// 写入过程中遇到的问题也会返回。
func (b *Buffer) WriteTo(w io.Writer) (n int64, err error) {
	b.lastRead = opInvalid
	if nBytes := b.Len(); nBytes > 0 {
		m, e := w.Write(b.buf[b.off:])
		if m > nBytes {
			panic("bytes.Buffer.WriteTo: invalid Write count")
		}
		b.off += m
		n = int64(m)
		if e != nil {
			return n, e
		}
		// 根据的定义，应已写入所有字节
		// io.Writer中的写入方法
		if m != nBytes {
			return n, io.ErrShortWrite
		}
	}
	// 缓冲区现在是空的；重置。
	b.Reset()
	return n, nil
}

// WriteByte将字节c追加到缓冲区，根据需要增加缓冲区。
// 返回的错误始终为零，但包含的错误与bufio.Writer的错误相匹配
// 写字节。如果缓冲区太大，WriteByte将死机
// 呃，太大了。
func (b *Buffer) WriteByte(c byte) error {
	b.lastRead = opInvalid
	m, ok := b.tryGrowByReslice(1)
	if !ok {
		m = b.grow(1)
	}
	b.buf[m] = c
	return nil
}

// WriteRune将Unicode代码点r的UTF-8编码附加到
// 缓冲区，返回其长度和一个错误，该错误始终为零，但为零
// 包括以匹配bufio。作者的笔迹。根据需要生长缓冲液；
// 如果它变得太大，WriteRune将因ErrTooLarge而恐慌。
func (b *Buffer) WriteRune(r rune) (n int, err error) {
	// 比较as uint32以正确处理负面符文。
	if uint32(r) < utf8.RuneSelf {
		b.WriteByte(byte(r))
		return 1, nil
	}
	b.lastRead = opInvalid
	m, ok := b.tryGrowByReslice(utf8.UTFMax)
	if !ok {
		m = b.grow(utf8.UTFMax)
	}
	n = utf8.EncodeRune(b.buf[m:m+utf8.UTFMax], r)
	b.buf = b.buf[:m+n]
	return n, nil
}

// Read从缓冲区读取下一个len（p）字节，或直到缓冲区
// 水排干了。返回值n是读取的字节数。如果
// 缓冲区没有要返回的数据，err为io.EOF（除非len（p）为零）；
// 否则为零。
func (b *Buffer) Read(p []byte) (n int, err error) {
	b.lastRead = opInvalid
	if b.empty() {
		// 缓冲区为空，请重置以恢复空间。
		b.Reset()
		if len(p) == 0 {
			return 0, nil
		}
		return 0, io.EOF
	}
	n = copy(p, b.buf[b.off:])
	b.off += n
	if n > 0 {
		b.lastRead = opRead
	}
	return n, nil
}

// Next返回一个包含缓冲区中接下来n个字节的片，
// 将缓冲区向前移动，就好像字节已通过读取返回一样。
// 如果缓冲区中的字节少于n个，Next将返回整个缓冲区。
// 该切片仅在下次调用读或写方法之前有效。
func (b *Buffer) Next(n int) []byte {
	b.lastRead = opInvalid
	m := b.Len()
	if n > m {
		n = m
	}
	data := b.buf[b.off : b.off+n]
	b.off += n
	if n > 0 {
		b.lastRead = opRead
	}
	return data
}

// ReadByte读取并返回缓冲区中的下一个字节。
// 如果没有可用字节，则返回错误io.EOF。
func (b *Buffer) ReadByte() (byte, error) {
	if b.empty() {
		// 缓冲区为空，请重置以恢复空间。
		b.Reset()
		return 0, io.EOF
	}
	c := b.buf[b.off]
	b.off++
	b.lastRead = opRead
	return c, nil
}

// ReadRune读取并返回下一个UTF-8编码的
// 缓冲区中的Unicode代码点。
// 如果没有可用字节，则返回的错误为io.EOF。
// 如果字节是错误的UTF-8编码，则
// 消耗一个字节并返回U+FFFD，1。
func (b *Buffer) ReadRune() (r rune, size int, err error) {
	if b.empty() {
		// 缓冲区为空，请重置以恢复空间。
		b.Reset()
		return 0, 0, io.EOF
	}
	c := b.buf[b.off]
	if c < utf8.RuneSelf {
		b.off++
		b.lastRead = opReadRune1
		return rune(c), 1, nil
	}
	r, n := utf8.DecodeRune(b.buf[b.off:])
	b.off += n
	b.lastRead = readOp(n)
	return r, n, nil
}

// 未读符文未读读符文返回的最后一个符文。
// 如果缓冲区上最近的读或写操作是
// 读符文不成功，未读符文返回错误。（在这方面）
// 它比未读字节更严格，后者将未读最后一个字节
// 从任何读取操作。）
func (b *Buffer) UnreadRune() error {
	if b.lastRead <= opInvalid {
		return errors.New("bytes.Buffer: UnreadRune: previous operation was not a successful ReadRune")
	}
	if b.off >= int(b.lastRead) {
		b.off -= int(b.lastRead)
	}
	b.lastRead = opInvalid
	return nil
}

var errUnreadByte = errors.New("bytes.Buffer: UnreadByte: previous operation was not a successful read")

// UnreadByte未读最近一次成功访问返回的最后一个字节
// 至少读取一个字节的读取操作。如果此后发生了一次写入
// 上次读取，如果上次读取返回错误，或者如果读取为零
// 字节，未读字节返回错误。
func (b *Buffer) UnreadByte() error {
	if b.lastRead == opInvalid {
		return errUnreadByte
	}
	b.lastRead = opInvalid
	if b.off > 0 {
		b.off--
	}
	return nil
}

// ReadBytes读取，直到输入中第一次出现delim，
// 返回一个包含数据的片段，该数据在该分隔符之前（包括该分隔符）。
// 如果ReadBytes在查找分隔符之前遇到错误，
// 它返回错误前读取的数据和错误本身（通常是io.EOF）。
// ReadBytes返回错误！=nil当且仅当返回的数据不以
// 德利姆。
func (b *Buffer) ReadBytes(delim byte) (line []byte, err error) {
	slice, err := b.readSlice(delim)
	// 返回切片的副本。缓冲区的后备数组可能会
	// 将被以后的调用覆盖。
	line = append(line, slice...)
	return line, err
}

// readSlice类似于ReadBytes，但返回对内部缓冲区数据的引用。
func (b *Buffer) readSlice(delim byte) (line []byte, err error) {
	i := IndexByte(b.buf[b.off:], delim)
	end := b.off + i + 1
	if i < 0 {
		end = len(b.buf)
		err = io.EOF
	}
	line = b.buf[b.off:end]
	b.off = end
	b.lastRead = opRead
	return line, err
}

// ReadString一直读取，直到输入中第一次出现delim，
// 返回一个字符串，该字符串包含在分隔符之前（包括该分隔符）的数据。
// 如果ReadString在查找分隔符之前遇到错误，
// 它返回错误前读取的数据和错误本身（通常是io.EOF）。
// ReadString返回错误！=nil当且仅当返回的数据未结束时
// 在熟食中。
func (b *Buffer) ReadString(delim byte) (line string, err error) {
	slice, err := b.readSlice(delim)
	return string(slice), err
}

// NewBuffer创建并初始化一个新的缓冲区，使用buf作为其
// 初始内容。新缓冲区拥有buf的所有权，而
// 呼叫方在此呼叫后不应使用buf。NewBuffer的目的是
// 准备缓冲区以读取现有数据。它还可以用于设置
// 用于写入的内部缓冲区的初始大小。为此,，
// buf应具有所需的容量，但长度为零。
// None
// 在大多数情况下，new（Buffer）（或仅声明一个Buffer变量）是
// 足以初始化缓冲区。
func NewBuffer(buf []byte) *Buffer { return &Buffer{buf: buf} }

// NewBufferString创建并初始化一个新的缓冲区，使用字符串s作为其
// 初始内容。其目的是准备一个缓冲区来读取现有数据
// 一串
// None
// 在大多数情况下，new（Buffer）（或仅声明一个Buffer变量）是
// 足以初始化缓冲区。
func NewBufferString(s string) *Buffer {
	return &Buffer{buf: []byte(s)}
}
